/*
 * Part of the ACID Project
 * Developed in 2011 by Morgan Taschuk
 */
package acid.plugin.expression.similarity;

import java.util.ArrayList;
import java.util.List;

/**
 * Takes the given vector and permutes it (changes the ordering) in order to
 * calculate the distance between randomised vectors
 *
 * Inspired by
 * http://www.programmerinterview.com/index.php/recursion/permutations-of-a-string/
 * @author morgan
 */
public abstract class PermuteVector
{

    private List<Double> distances;
    private double[] measure;

    public PermuteVector(double[] measure)
    {
        this.measure = measure;
        distances = new ArrayList<Double>();
    }

    public void permute(double[] in)
    {
        int inputLength = in.length;
        boolean[] used = new boolean[inputLength];
        ArrayList<Double> outputString = new ArrayList<Double>();
        //char[] in = input.toCharArray();

        doPermute(in, outputString, used, inputLength, 0);
    }
    int numPermutations = 0;

    protected boolean doPermute(double[] in, ArrayList<Double> permutedArr,
            boolean[] used, int inputLength, int level)
    {
        if (level == inputLength && numPermutations < 120)
        {
            numPermutations++;
            double dist = calculateDistance(getDoubleArray(permutedArr), measure);
            distances.add(dist);
        }
        else if (numPermutations >=120)
        {
            return true;
        }

        for (int i = 0; i < inputLength; ++i)
        {

            if (used[i])
            {
                continue;
            }

            permutedArr.add(in[i]);
            used[i] = true;
            if (doPermute(in, permutedArr, used, inputLength, level + 1))
                return true;
            used[i] = false;
            permutedArr.remove(permutedArr.size() - 1);
        }
        return false;
    }

    protected abstract double calculateDistance(double[] u, double[] v);

    public double[] getDistances()
    {
        return getDoubleArray(distances);
    }

    private double[] getDoubleArray(List<Double> doubleArr)
    {
        double[] permuted = new double[doubleArr.size()];
        for (int i = 0; i < doubleArr.size(); i++)
        {
            //System.out.print(doubleArr.get(i) + " ");
            permuted[i] = doubleArr.get(i);
        }
        return permuted;
    }
}
